﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Diagnostics;
using Luna;
using System.IO;
using System.ComponentModel;
using System.Drawing.Design;

namespace VulnDB.Action.DataCollectors.Actions {
	public class ScanNVDProductAction : DataCollectorAction {

		public string NVDXmlRepository { get; set; }

		public List<string> NVDXmlRepositories { get; private set; }

		//[Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
		public string Products { get; private set; }

		public string Output { get; set; }

		public ScanNVDProductAction() {
			NVDXmlRepositories = new List<string>();
			Output = "scannvd.txt";
			Name = "ScanNVDProductAction";
			Products = "firefox";
			ExecutionMode = VulnDBExplorer.Framework.Impl.ActionExecutionMode.SeparatedThread;
			Text = Name;
		}

		protected override void onExecute(object sender, Luna.Framework.ActionExecutionArgs args) {
			base.onExecute(sender, args);
			if (!ActionParameterForm.showPropertyForm(this))
				return;

			Console.log("Searching NVD entries...");
			StreamWriter output = new StreamWriter(Output);
			foreach (string repo in NVDXmlRepositories) 
				if (repo.fileExists()) {
					Console.write("Searching {0}...", repo.getFileName());
					var res = scanForProduct(Products.Split(';'), repo);
					foreach (var item in res) {
						output.WriteLine("{0},{1},{2}", item.Item1, item.Item2, item.Item3);
					}
					Console.writeLine("{0} entr(ies) found.", res.Count);
				}
			output.Close();
			Console.log("Completed");
		}

		public void test() {
			NVDXmlRepository = @"d:\Documents\Activities\Trento\PhD\Experiments\NVD\nvdcve-2.0-2009.xml";
			var res = scanForProduct(new string[] {"apache", "redhat", "firefox"}, NVDXmlRepository);
			foreach (var item in res)
				System.Console.WriteLine("{0}, {1}, {2}", item.Item1, item.Item2, item.Item3);
		}

		public ISet<Tuple<string, string, string>> scanForProduct(IList<string> products, string XmlRepository) {
			XmlReaderSettings settings = new XmlReaderSettings();
			settings.IgnoreWhitespace = true;
			
			SortedSet<Tuple<string, string, string>> result = new SortedSet<Tuple<string, string, string>>();

			using (XmlReader reader = XmlReader.Create(XmlRepository, settings)) {
				while (reader.ReadToFollowing("entry")) {
					string cveID = null;
					XmlReader inner = reader.ReadSubtree();
					if (reader.MoveToAttribute("id")) {
						while (reader.ReadAttributeValue())
							if (reader.NodeType == XmlNodeType.Text)
								cveID = reader.Value;
					}

					if (!string.IsNullOrWhiteSpace(cveID))
						while (inner.ReadToFollowing("vuln:product")) {
							string content = inner.ReadString();
							foreach(string productName in products) 
								if (content.IndexOf(productName) >= 0) {
									int idx = content.LastIndexOf(':');
									if (idx >= 0) {
										string ver = content.Substring(idx + 1).TrimEnd();
										result.Add(Tuple.Create(productName, cveID, ver));
									}
								}
						}
					inner.Close();
				}
			}

			return result;
		}
	}
}
